
/**
  ******************************************************************************
  * Copyright 2021 The grapilot Authors. All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  * 
  * @file       gp_arming.h
  * @author     baiyang
  * @date       2021-8-12
  ******************************************************************************
  */

#pragma once

#ifdef __cplusplus
extern "C"{
#endif

/*----------------------------------include-----------------------------------*/
#include <stdbool.h>
#include <stdint.h>

#include <common/gp_defines.h>
#include <mavproxy/mavproxy.h>
/*-----------------------------------macro------------------------------------*/
// auxiliary authorisation
#define AUX_AUTH_COUNT_MAX 3      // maximum number of auxiliary authorisers
#define AUX_AUTH_STR_LEN   42     // maximum length of failure message (50-8 for "PreArm: ")

/*----------------------------------typedef-----------------------------------*/
typedef enum {
    ARMING_CHECK_ALL         = (1U << 0),
    ARMING_CHECK_BARO        = (1U << 1),
    ARMING_CHECK_COMPASS     = (1U << 2),
    ARMING_CHECK_GPS         = (1U << 3),
    ARMING_CHECK_INS         = (1U << 4),
    ARMING_CHECK_PARAMETERS  = (1U << 5),
    ARMING_CHECK_RC          = (1U << 6),
    ARMING_CHECK_VOLTAGE     = (1U << 7),
    ARMING_CHECK_BATTERY     = (1U << 8),
    ARMING_CHECK_AIRSPEED    = (1U << 9),
    ARMING_CHECK_LOGGING     = (1U << 10),
    ARMING_CHECK_SWITCH      = (1U << 11),
    ARMING_CHECK_GPS_CONFIG  = (1U << 12),
    ARMING_CHECK_SYSTEM      = (1U << 13),
    ARMING_CHECK_MISSION     = (1U << 14),
    ARMING_CHECK_RANGEFINDER = (1U << 15),
    ARMING_CHECK_CAMERA      = (1U << 16),
    ARMING_CHECK_AUX_AUTH    = (1U << 17),
    ARMING_CHECK_VISION      = (1U << 18),
    ARMING_CHECK_FFT         = (1U << 19),
} ArmingChecks;

typedef enum {
    ARMING_CHECK_RUDDER = 0,
    ARMING_CHECK_MAVLINK = 1,
    ARMING_CHECK_AUXSWITCH = 2,
    ARMING_CHECK_MOTORTEST = 3,
    ARMING_CHECK_SCRIPTING = 4,
    ARMING_CHECK_TERMINATION = 5, // only disarm uses this...
    ARMING_CHECK_CPUFAILSAFE = 6, // only disarm uses this...
    ARMING_CHECK_BATTERYFAILSAFE = 7, // only disarm uses this...
    ARMING_CHECK_SOLOPAUSEWHENLANDED = 8, // only disarm uses this...
    ARMING_CHECK_AFS = 9, // only disarm uses this...
    ARMING_CHECK_ADSBCOLLISIONACTION = 10, // only disarm uses this...
    ARMING_CHECK_PARACHUTE_RELEASE = 11, // only disarm uses this...
    ARMING_CHECK_CRASH = 12, // only disarm uses this...
    ARMING_CHECK_LANDED = 13, // only disarm uses this...
    ARMING_CHECK_MISSIONEXIT = 14, // only disarm uses this...
    ARMING_CHECK_FENCEBREACH = 15, // only disarm uses this...
    ARMING_CHECK_RADIOFAILSAFE = 16, // only disarm uses this...
    ARMING_CHECK_DISARMDELAY = 17, // only disarm uses this...
    ARMING_CHECK_GCSFAILSAFE = 18, // only disarm uses this...
    ARMING_CHECK_TERRRAINFAILSAFE = 19, // only disarm uses this...
    ARMING_CHECK_FAILSAFE_ACTION_TERMINATE = 20, // only disarm uses this...
    ARMING_CHECK_TERRAINFAILSAFE = 21, // only disarm uses this...
    ARMING_CHECK_MOTORDETECTDONE = 22, // only disarm uses this...
    ARMING_CHECK_BADFLOWOFCONTROL = 23, // only disarm uses this...
    ARMING_CHECK_EKFFAILSAFE = 24, // only disarm uses this...
    ARMING_CHECK_GCS_FAILSAFE_SURFACEFAILED = 25, // only disarm uses this...
    ARMING_CHECK_GCS_FAILSAFE_HOLDFAILED = 26, // only disarm uses this...
    ARMING_CHECK_TAKEOFFTIMEOUT = 27, // only disarm uses this...
    ARMING_CHECK_AUTOLANDED = 28, // only disarm uses this...
    ARMING_CHECK_PILOT_INPUT_FAILSAFE = 29, // only disarm uses this...
    ARMING_CHECK_TOYMODELANDTHROTTLE = 30, // only disarm uses this...
    ARMING_CHECK_TOYMODELANDFORCE = 31, // only disarm uses this...
    ARMING_CHECK_LANDING = 32, // only disarm uses this...
    ARMING_CHECK_UNKNOWN = 100,
} ArmingMethod;

typedef enum {
    ARMING_NO           = 0,
    ARMING_YES_MIN_PWM  = 1,
    ARMING_YES_ZERO_PWM = 2
} ArmingRequired;

// rudder arming support
typedef enum {
    ARMING_IS_DISABLED  = 0, // DISABLED leaks in from vehicle defines.h
    ARMING_ARMONLY   = 1,
    ARMING_ARMDISARM = 2
} RudderArming;

typedef enum {
    MIS_ITEM_CHECK_LAND          = (1 << 0),
    MIS_ITEM_CHECK_VTOL_LAND     = (1 << 1),
    MIS_ITEM_CHECK_DO_LAND_START = (1 << 2),
    MIS_ITEM_CHECK_TAKEOFF       = (1 << 3),
    MIS_ITEM_CHECK_VTOL_TAKEOFF  = (1 << 4),
    MIS_ITEM_CHECK_RALLY         = (1 << 5),
    MIS_ITEM_CHECK_MAX
} MIS_ITEM_CHECK;

typedef enum {
    AUTH_STATE_NO_RESPONSE = 0,
    AUTH_STATE_FAILED,
    AUTH_STATE_PASSED
} AuxAuthStates;

typedef struct {
    struct gp_arming_ops *ops;

    // Parameters
    Param_int8                 require;
    Param_int32                checks_to_perform;      // bitmask for which checks are required
    Param_float                accel_error_threshold;
    Param_int8                 _rudder_arming;
    Param_int32                _required_mission_items;

    // internal members
    bool                    armed;
    uint32_t                last_accel_pass_ms[3];  // 3组IMU
    uint32_t                last_gyro_pass_ms[3];   // 3组IMU

    AuxAuthStates aux_auth_state[AUX_AUTH_COUNT_MAX];  // state of each auxiliary authorisation
    uint8_t aux_auth_count;     // number of auxiliary authorisers
    uint8_t aux_auth_fail_msg_source;   // authorisation id who set aux_auth_fail_msg
    char* aux_auth_fail_msg;    // buffer for holding failure messages
    bool aux_auth_error;        // true if too many auxiliary authorisers

    // method that was last used for disarm; invalid unless the
    // vehicle has been disarmed at least once.
    ArmingMethod _last_disarm_method;
}gp_arming;

/**
 * uart operators
 */
struct gp_arming_ops {
    bool (*arm)(gp_arming* arming, ArmingMethod method, bool do_arming_checks);    //bool do_arming_checks=true
    bool (*disarm)(gp_arming* arming, ArmingMethod method, bool do_disarm_checks); //bool do_arming_checks=true
    
    // pre_arm_checks() is virtual so it can be modified in a vehicle specific subclass
    bool (*pre_arm_checks)(gp_arming* arming, bool report);

    // some arming checks have side-effects, or require some form of state
    // change to have occurred, and thus should not be done as pre-arm
    // checks.  Those go here:
    bool (*arm_checks)(gp_arming* arming, ArmingMethod method);

    bool (*barometer_checks)(gp_arming* arming, bool report);
    bool (*ins_checks)(gp_arming* arming, bool report);
    bool (*gps_checks)(gp_arming* arming, bool report);
    bool (*board_voltage_checks)(gp_arming* arming, bool report);

    bool (*rc_calibration_checks)(gp_arming* arming, bool report);
    bool (*system_checks)(gp_arming* arming, bool report);
    bool (*proximity_checks)(gp_arming* arming, bool report);
    // mandatory checks that cannot be bypassed.  This function will only be called if ARMING_CHECK is zero or arming forced
    bool (*mandatory_checks)(gp_arming* arming, bool report);
};

/*----------------------------------variable----------------------------------*/

/*-------------------------------------os-------------------------------------*/

/*----------------------------------function----------------------------------*/
// 构造函数
void arming_ctor(gp_arming* arming);

// mandatory checks that cannot be bypassed.  This function will only be called if ARMING_CHECK is zero or arming forced
bool arming_mandatory_checks(gp_arming* arming, bool report);

bool arming_is_armed(gp_arming* arming);

//returns true if arming occurred successfully
bool arming_arm(gp_arming* arming, ArmingMethod method, const bool do_arming_checks);

//returns true if disarming occurred successfully
bool arming_disarm(gp_arming* arming, ArmingMethod method, bool do_disarm_checks);

bool arming_pre_arm_checks(gp_arming* arming, bool report);

bool arming_check_enabled(gp_arming * arming, const ArmingChecks check);

bool arming_arm_checks(gp_arming* arming, ArmingMethod method);

MAV_SEVERITY arming_check_severity(gp_arming * arming, const ArmingChecks check);
void arming_check_failed(gp_arming * arming, bool report, const char *fmt, ...);
void arming_check_failed2(gp_arming * arming, const ArmingChecks  check, bool report, const char *fmt, ...);

bool arming_rc_calibration_checks(gp_arming * arming, bool report);

// Copter and sub share the same RC input limits
// Copter checks that min and max have been configured by default, Sub does not
bool arming_rc_checks_copter_sub(gp_arming * arming, const bool display_failure);

/*------------------------------------test------------------------------------*/

#ifdef __cplusplus
}
#endif



